﻿using ModbusCase.Lib;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace ModbusCase
{
    /// <summary>
    /// RtuCaseByThird.xaml 的交互逻辑
    /// </summary>
    public partial class RtuCaseBySelf : Window, INotifyPropertyChanged
    {
        SerialPort serialPort;

        ModbusRTUNew modbusRTUNew;

        public RtuCaseBySelf()
        {
            InitializeComponent();
            DataContext = this;  // 设置数据上下文为当前窗口实例

            OpenPort();  // 打开串口

            #region 读取三个输出线圈状态
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        // 每隔1秒读取三个输出线圈
                        ReadOutputStatus();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 数字量输入
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadInputStatus();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 模拟量输出
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadOutputNum();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 模拟量输入
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadInputNum();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 读float
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadFloat();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion


            #region 读Int
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadInt();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion

            #region 读Short
            Task.Run(async () =>
            {
                while (true)
                {
                    Dispatcher.Invoke(() =>
                    {
                        ReadShort();
                    });

                    await Task.Delay(1000);
                }
            });
            #endregion

        }

        #region 打开串口
        /// <summary>
        /// 打开串口
        /// </summary>
        private void OpenPort()
        {
            serialPort = new SerialPort("COM19");
            serialPort.BaudRate = 9600;
            serialPort.DataBits = 8;
            serialPort.Parity = Parity.None;
            serialPort.StopBits = StopBits.One;

            serialPort.ReadTimeout = 500;//读超时时间 单位毫秒
            serialPort.Open();
        }
        #endregion

        #region 属性值改变通知
        public event PropertyChangedEventHandler? PropertyChanged;

        /// <summary>
        /// 属性值改变通知
        /// </summary>
        /// <param name="propName"></param>
        private void PropChanged(string propName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
        }
        #endregion

        #region 三个输出状态
        private bool outputStatus0;

        public bool OutputStatus0
        {
            get { return outputStatus0; }
            set
            {
                outputStatus0 = value;
                PropChanged("OutputStatus0");  // 属性值改变通知UI更新
            }
        }

        private bool outputStatus1;

        public bool OutputStatus1
        {
            get { return outputStatus1; }
            set
            {
                outputStatus1 = value;
                PropChanged("OutputStatus1");  // 属性值改变通知UI更新
            }
        }

        private bool outputStatus2;

        public bool OutputStatus2
        {
            get { return outputStatus2; }
            set
            {
                outputStatus2 = value;
                PropChanged("OutputStatus2");  // 属性值改变通知UI更新
            }
        }

        /// <summary>
        /// 读取三个状态输出
        /// </summary>
        private void ReadOutputStatus()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }
                bool[] result = modbusRTUNew.ReadBools(0x01, FuncCode.ReadCoils, 0, 3);

                OutputStatus0 = result[0];
                OutputStatus1 = result[1];
                OutputStatus2 = result[2];
            }
        }

        /// <summary>
        /// 第一个状态操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb0_Click(object sender, RoutedEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }
                modbusRTUNew.WriteSingleCoil(0x01, 0, OutputStatus0);
            }
        }

        /// <summary>
        /// 第二个状态操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb1_Click(object sender, RoutedEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }
                modbusRTUNew.WriteSingleCoil(0x01, 1, OutputStatus1);
            }
        }

        /// <summary>
        /// 第三个状态操作
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cb2_Click(object sender, RoutedEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }
                modbusRTUNew.WriteSingleCoil(0x01, 2, OutputStatus2);
            }
        }
        #endregion

        #region 数字量输入
        private void ReadInputStatus()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }
                bool[] result = modbusRTUNew.ReadBools(0x01, FuncCode.ReadDiscreteInputs, 0, 3);

                if (result[0])
                {
                    BorderLight0.Background = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    BorderLight0.Background = new SolidColorBrush(Colors.LightGray);
                }

                if (result[1])
                {
                    BorderLight1.Background = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    BorderLight1.Background = new SolidColorBrush(Colors.LightGray);
                }

                if (result[2])
                {
                    BorderLight2.Background = new SolidColorBrush(Colors.Red);
                }
                else
                {
                    BorderLight2.Background = new SolidColorBrush(Colors.LightGray);
                }
            }
        }
        #endregion

        #region 模拟量输出 操作
        private void ReadOutputNum()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                short[] result = modbusRTUNew.ReadReg16(0x01, FuncCode.ReadHoldingRegisters, 0, 4);
                sVar0.Value = result[0];
                sVar1.Value = result[1];
                sVar2.Value = result[2];
                sVar3.Value = result[3];
            }
        }

        private void sVar0_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteSingleReg(0x01, 0, (short)sVar0.Value);
            }
        }

        private void sVar1_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteSingleReg(0x01, 1, (short)sVar1.Value);
            }
        }

        private void sVar2_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteSingleReg(0x01, 2, (short)sVar2.Value);
            }
        }

        private void sVar3_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteSingleReg(0x01, 3, (short)sVar3.Value);
            }
        }

        #endregion

        #region 模拟量的输入
        private void ReadInputNum()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                short[] result = modbusRTUNew.ReadReg16(0x01, FuncCode.ReadInputRegisters, 0, 4);
                txtInputReg0.Text = result[0].ToString();
                txtInputReg1.Text = result[1].ToString();
                txtInputReg2.Text = result[2].ToString();
                txtInputReg3.Text = result[3].ToString();
            }
        }
        #endregion

        #region 数字类型 操作
        private void ReadFloat()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                float[] results = modbusRTUNew.ReadReg32Float(0x01, FuncCode.ReadHoldingRegisters, 8, 1, Endian.BigEndian);
                txtFloat.Text = results[0].ToString();
            }
        }

        private void txtFloat_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteMultipleReg32Float(0x01, 8, [float.Parse(txtFloat.Text)], Endian.BigEndian);
            }
        }

        private void ReadInt()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                int[] results = modbusRTUNew.ReadRegInt32(0x01, FuncCode.ReadHoldingRegisters, 10, 1, Endian.BigEndian);
                txtInt.Text = results[0].ToString();
            }
        }

        private void txtInt_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteMultipleReg32Int(0x01, 10, [int.Parse(txtInt.Text)], Endian.BigEndian);
            }
        }

        private void ReadShort()
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                short[] results = modbusRTUNew.ReadReg16(0x01, FuncCode.ReadHoldingRegisters, 12, 1);
                txtShort.Text = results[0].ToString();
            }
        }

        private void txtShort_TextChanged(object sender, TextChangedEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                if (modbusRTUNew == null)
                {
                    modbusRTUNew = new ModbusRTUNew(serialPort);
                }

                modbusRTUNew.WriteSingleReg(0x01, 12, short.Parse(txtShort.Text));
            }
        }


        #endregion

        private void Window_Closed(object sender, EventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();  // 确保在窗口关闭时关闭串口连接
            }
        }
    }
}
